package edu.uba.fcen.estimacion.cubrimiento;

import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.uba.fcen.estimacion.cubrimiento.estrategias.AllTheWordsEveryTimeStrategy;
import edu.uba.fcen.estimacion.cubrimiento.estrategias.CoverContext;
import edu.uba.fcen.estimacion.cubrimiento.estrategias.DistinctAndUniqueWordsStrategy;
import edu.uba.fcen.estimacion.word.selection.Pair;
import edu.uba.fcen.estimacion.word.selection.WriterResult;
import edu.uba.fcen.estimacion.word.selection.constants.Constants;
import edu.uba.fcen.estimacion.word.selection.filter.FilterWords;
import edu.uba.fcen.estimacion.word.selection.filter.FilterWordsFactory;

public class Cover {

	
	public static void main(String[] args) {
		String wikipediaFile = args[0];
		String cuentoFile = args[1];
		int limit = Integer.valueOf(args[2]);
		
		File wikinewsDirectory = new File(Constants.WIKINEWS_FREELING_OUT_PATH);
		int increaseWords = 100;
		int amountOfWords = 100;
		CoverContext context;
		List<Double> avgStrategy = new ArrayList<Double>();
		WriterResult writer = new WriterResult("results.txt");
		
		while (amountOfWords < limit) {
			final Map<String, Double> words = takeWordsFromDataSet(amountOfWords, wikipediaFile, cuentoFile);
			for(File outFreelingFile : wikinewsDirectory.listFiles()) {
				if (isOutFile(outFreelingFile)) {
					context = new CoverContext(new DistinctAndUniqueWordsStrategy(outFreelingFile, words));
					avgStrategy.add(context.execute());
				}
			}
			final double calculateAvg = calculateAvg(avgStrategy);
			System.out.println("Estrategia 2 amount: " + words.size() + " rate: " + calculateAvg);
			
			DecimalFormat df = new DecimalFormat("###.########################");
			writer.writeWithEnter(String.valueOf(words.size()) + ";" + df.format(calculateAvg));
			
			avgStrategy.clear();
			amountOfWords += increaseWords;
		}
		
		writer.close();
	}



	private static double calculateAvg(final List<Double> avgStrategy) {
		double result = 0d;
		for (double value : avgStrategy) {
			result += value;
		}
		return result/avgStrategy.size();
	}



	private static Map<String, Double> takeWordsFromDataSet(int amountOfWords, String wikipediaFile, String cuentoFile) {
		FilterWords fwCuento = FilterWordsFactory.getNormalLineByLineFilter(cuentoFile);
		FilterWords fwWikipedia = FilterWordsFactory.getNormalLineByLineFilter(wikipediaFile);
		Map<String, Double> map = new HashMap<String, Double>();
		String [] splited;
		String line, word;
		for (int count = 0; count <= amountOfWords; count++) {
			line = fwCuento.readLine();
			splitAndAdd(map, line);
			line = fwWikipedia.readLine();
			splitAndAdd(map, line);
		}
		writeResult(map);
		return map;
	}

	private static void writeResult(Map<String, Double> map) {
		WriterResult writer = new WriterResult("NormalizedAndInterpolatedWords.txt");
		for (Pair<String, Double> pair : getSortedList(map)) {
				writer.writeWithEnter(pair.getX() + "\t\t\t" + pair.getY());
		}
	}

	private static List<Pair<String, Double>> getSortedList(Map<String, Double> map) {
		List<Pair<String, Double>> sortedList = new ArrayList<Pair<String,Double>>(map.size());
		
		for (String key : map.keySet()) {
			sortedList.add(new Pair<String, Double>(key, map.get(key)));
		}
		
		Collections.sort(sortedList, new Comparator<Pair<String,Double>>() {
			@Override
			public int compare(Pair<String,Double> o1, Pair<String,Double> o2) {
				return o2.getY().compareTo(o1.getY());
			}
		});
		return sortedList;
	}
	
	/**
	 * Add and calculate the interpolation when is necessary
	 * @param map
	 * @param line
	 */
	private static void splitAndAdd(Map<String, Double> map,
			String line) {
		String[] splited;
		String word; 
		Double ocurrence;
		if (line != null) {
			splited = line.split("\t\t\t");
			word = splited[0];
			ocurrence = Double.valueOf(splited[1]);
			if (map.containsKey(word)) {
				Double previousOcurrence = map.get(word);
				map.put(word, (ocurrence + previousOcurrence) / 2);
			} else {
				map.put(word, ocurrence);
			}
		}
	}

	private static boolean isOutFile(File outFreelingFile) {
//		return outFreelingFile.getName().startsWith("out-wiki-");
		return outFreelingFile.getName().startsWith("out-");
	}
	
}
